package com.captjack.validator.handler;

import org.hibernate.validator.HibernateValidator;
import org.springframework.stereotype.Component;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.validation.executable.ExecutableValidator;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Set;

/**
 * Description description.....
 *
 * @author Jack Sparrow
 * @version 1.0.0
 * @date 2018/8/5 00:52
 * package com.captjack.validator.handler
 */
@Component
public class ParamValidatorHandler {

    /**
     * 快速模式校验工厂类
     */
    private final ValidatorFactory fastValidatorFactory = Validation.byProvider(HibernateValidator.class)
            .configure()
            .addProperty("hibernate.validator.fail_fast", "true")
            .buildValidatorFactory();

    /**
     * 快速模式基本数据类型校验
     */
    private final ExecutableValidator fastExecutableValidator = fastValidatorFactory.getValidator().forExecutables();

    /**
     * 快速模式自定义数据类型校验
     */
    private final Validator fastValidator = fastValidatorFactory.getValidator();

    /**
     * 默认校验工厂类，返回所有错误类型
     */
    private final ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();

    /**
     * 默认基本数据类型校验，返回所有错误类型
     */
    private final ExecutableValidator executableValidator = validatorFactory.getValidator().forExecutables();

    /**
     * 默认自定义数据类型校验，返回所有错误类型
     */
    private final Validator validator = validatorFactory.getValidator();

    /**
     * 校验函数中的基本数据类型参数
     *
     * @param object 对象
     * @param method 方法
     * @param params 参数
     * @param <T>    指定返回范型
     * @return 返回值
     */
    public <T> Set<ConstraintViolation<T>> validMethodParams(T object, Method method, Object[] params, boolean isFast) {
        return isFast ? this.fastExecutableValidator.validateParameters(object, method, params) : this.executableValidator.validateParameters(object, method, params);
    }

    public <T> Set<ConstraintViolation<T>> validBeanParams(T entity, boolean isFast) {
        return isFast ? this.fastValidator.validate(entity) : this.validator.validate(entity);
    }

    /**
     * 判断一个类是否为基本数据类型。
     *
     * @param clazz 要判断的类。
     * @return true 表示为基本数据类型。
     */
    public boolean isBaseDataType(Class clazz) {
        return clazz.isPrimitive() ||
                clazz.equals(String.class) ||
                clazz.equals(Integer.class) ||
                clazz.equals(Byte.class) ||
                clazz.equals(Long.class) ||
                clazz.equals(Double.class) ||
                clazz.equals(Float.class) ||
                clazz.equals(Character.class) ||
                clazz.equals(Short.class) ||
                clazz.equals(BigDecimal.class) ||
                clazz.equals(BigInteger.class) ||
                clazz.equals(Boolean.class);
    }

}
